//
//  BMUserManager.m
//  BicycleMap
//
//  Created by vedon on 5/15/16.
//  Copyright © 2016 Qianqian. All rights reserved.
//

#define kQuesryUserByIdCMD @"select * from '%@'"
#define KUserInfo @"BMUserInfo"

#import "BMUserManager.h"
#import "BMUserTable.h"
#import "AVQuery.h"


@interface BMUserManager ()
@property (nonatomic,strong) AVObject *av_userInfo;
@property (nonatomic,strong) BMUserTable *userTable;
@property (nonatomic,strong) BMUserInfo *currentUserInfo;
@end

@implementation BMUserManager

+ (instancetype)shareManager
{
    
    static BMUserManager *shareInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shareInstance = [[BMUserManager alloc] init];
    });
    
    return shareInstance;
}

- (instancetype)init
{
    self = [super init];
    if (self)
    {
        self.userTable = [[BMUserTable alloc] init];
        NSError *fetchError = nil;
        self.currentUserInfo = (BMUserInfo *)[self.userTable findLatestRecordWithError:&fetchError];
        
        if (self.currentUserInfo)
        {
            self.av_userInfo = [[AVObject alloc] initWithClassName:KUserInfo];
            self.av_userInfo.objectId = self.currentUserInfo.avObjectId;
            [self updateAvObjectWithUserInfo:self.currentUserInfo];
        }
        
    }
    return self;
}

#pragma mark - Public

- (BOOL)isLogin
{
    return self.currentUserInfo != nil;
}

- (BOOL)isUserAlreadyExist:(NSString *)mobile
{
    AVQuery *query = [[AVQuery alloc] initWithClassName:KUserInfo];
    [query whereKey:@"mobile" equalTo:mobile];
    AVObject *queryResult = [query getFirstObject];
    
    return (queryResult != nil);
}

- (void)save
{
    [self saveWithUserInfo:self.currentUserInfo completedBlock:nil];
}

- (void)logout
{
    NSError *queryError = nil;
    NSArray <BMUserInfo *>* account =  (NSArray <BMUserInfo *>*)[self.userTable findAllWithSQL:[NSString stringWithFormat:kQuesryUserByIdCMD,@"BMUserTable"] params:nil error:&queryError];
    
    assert(queryError == nil);
    
    
    [account enumerateObjectsUsingBlock:^(BMUserInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        NSError *deleteError = nil;
        [self.userTable deleteRecord:obj error:&deleteError];
    }];
    
    
    self.currentUserInfo =  nil;
}

- (void)saveWithUserInfo:(BMUserInfo *)userInfo completedBlock:(BMUserInfoCompletedBlock)completedBlock
{
    
    if (userInfo)
    {
        NSError *insertError = nil;
        if (self.currentUserInfo)
        {
            [self.userTable deleteRecord:self.currentUserInfo error:nil];
            self.av_userInfo.objectId = self.currentUserInfo.avObjectId;
            self.currentUserInfo = userInfo;
        }
        else
        {
            [self createAccountWithUserInfoIfNeed:userInfo];
        }
        
        
        [self.userTable insertRecord:userInfo error:&insertError];
        NSAssert(insertError == nil, nil);

        [self.av_userInfo saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
            
            if (!error)
            {
                self.currentUserInfo.avObjectId = self.av_userInfo.objectId;
                [self.userTable updateRecord:self.currentUserInfo error:nil];
            }
            
            
            if (completedBlock) {
                completedBlock(self.av_userInfo,error);
            }
        }];
    }
}

- (void)refreshUserInfoWithCompletedBlock:(BMUserInfoCompletedBlock)completedBlock
{
    if (self.av_userInfo)
    {
        [self.av_userInfo refreshInBackgroundWithBlock:^(AVObject *object, NSError *error) {
            
            [self updateUserInfo:self.currentUserInfo withAVObject:object];
            
            if (completedBlock)
            {
                completedBlock(object,error);
            }
        }];
    }
}


- (void)fetchUserInfoWithName:(NSString *)name completedBlock:(BMUserInfoCompletedBlock)completedBlock
{
    
    AVQuery *query = [[AVQuery alloc] initWithClassName:KUserInfo];
    [query whereKey:@"name" equalTo:name];
    
    [query getFirstObjectInBackgroundWithBlock:^(AVObject *object, NSError *error) {
    
        if (object && error == nil)
        {
            [self updateUserInfo:self.currentUserInfo withAVObject:object];
            if (completedBlock)
            {
                completedBlock(object,error);
            }
        }
    }];
    
}

- (void)updateUserInfoWithUserInfo:(BMUserInfo *)userInfo completedBlock:(BMUserInfoCompletedBlock)completedBlock
{
    
    if (userInfo)
    {
        NSAssert(self.av_userInfo, nil);
        [self updateAvObjectWithUserInfo:userInfo];
        [self.av_userInfo saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
            
            if (!error)
            {
                self.currentUserInfo.avObjectId = self.av_userInfo.objectId;
            }
            
            if (completedBlock) {
                completedBlock(self.av_userInfo,error);
            }
            
        }];
    }
}

- (void)syncUserLocationToServer:(CLLocationCoordinate2D)location
{
    [self.currentUserInfo setUserLocation:location];
    [self updateUserInfoWithUserInfo:self.currentUserInfo completedBlock:nil];
    
}

- (void)uploadUserAvatar:(UIImage *)image completedBlock:(BMUserUploadFileCompletedBlock)completedBlock
{
    NSData *data = UIImageJPEGRepresentation(image, 0.2);
    NSString *fileName = [NSString stringWithFormat:@"%@_Avatar",self.currentUserInfo.username];
    AVFile *file = [AVFile fileWithName:fileName data:data];
    [file saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        
        if (completedBlock)
        {
            completedBlock(file.url,error);
        }
        
    }];
}

- (void)fetchFriendsListWithCompletedBlock:(BMFetchFriendListCompletedBlock)completedBlock
{
    
    AVQuery *query = [[AVQuery alloc] initWithClassName:KUserInfo];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        
        NSMutableArray *friendList = [NSMutableArray array];
        if (objects.count)
        {
            
            [objects enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
                AVObject *tempObject = obj;
                BMUserInfo *userInfo = [[BMUserInfo alloc] init];
                [self updateUserInfo:userInfo withAVObject:tempObject];
                if (![userInfo.mobile isEqualToString:self.currentUserInfo.mobile])
                {
                    [friendList addObject:userInfo];
                }
                
            }];
        }
        
        if (completedBlock)
        {
            completedBlock(friendList);
        }
    }];
    
}

#pragma mark - Private


- (void)updateUserInfo:(BMUserInfo *)userInfo withAVObject:(AVObject *)object
{
    userInfo.username = [object objectForKey:@"name"];
    userInfo.mobile = [object objectForKey:@"mobile"];
    userInfo.location = [object objectForKey:@"location"];
    userInfo.avatarUrl = [object objectForKey:@"avatarUrl"];
}

- (void)updateAvObjectWithUserInfo:(BMUserInfo *)userInfo
{
    [self.av_userInfo setObject:userInfo.username forKey:@"name"];
    [self.av_userInfo setObject:userInfo.mobile forKey:@"mobile"];
    [self.av_userInfo setObject:userInfo.location forKey:@"location"];
    [self.av_userInfo setObject:userInfo.avatarUrl forKey:@"avatarUrl"];
    
}

- (void)createAccountWithUserInfoIfNeed:(BMUserInfo *)userInfo
{
    AVQuery *query = [[AVQuery alloc] initWithClassName:KUserInfo];
    [query whereKey:@"mobile" equalTo:userInfo.mobile];
    AVObject *queryResult = [query getFirstObject];
    if (queryResult)
    {
        self.av_userInfo = queryResult;
    }
    else
    {
        self.av_userInfo = [[AVObject alloc] initWithClassName:KUserInfo];
        [self updateAvObjectWithUserInfo:userInfo];
    }
    
    self.currentUserInfo = userInfo;
}
#pragma mark  - Getter & Setter


@end
